package org.lexapp
{
	import mx.events.FlexEvent;
	import mx.managers.PopUpManager;
	import org.lexapp.model.BookmarkVO;
	import spark.components.TitleWindow;
	import org.lexapp.components.AuthPopup;

	import com.carlcalderon.arthropod.Debug;
	import flash.events.Event;
	import mx.collections.ArrayList;
	import pl.maliboo.ftp.FTPFile;
	import spark.components.WindowedApplication;
	import org.lexapp.ftp.RemoteFileBrowserApplication;
	
	[Event(name = "EVENT_DIRECTORY_LISTING_SUCCESS", type = "flash.events.Event")] 
	
	/**
	 * ...
	 * @author lex@silex.tv
	 */
	public class Lexapplication extends WindowedApplication
	{
		/**
		 * default port number
		 */
		public static const DEFAULT_PORT:Number = 21;
		/**
		 * list of files in the current directory<br />
		 */
		[Bindable]
		protected var filesArray:ArrayList = new ArrayList;
		/**
		 * current path<br />
		 */
		[Bindable]
		protected var currentPath:String = "";
		/**
		 * current host / port<br />
		 * may contain the port (host:port)<br />
		 * used for display / read only
		 */
		[Bindable]
		protected var currentHostAndPort:String = "";
		/**
		 * current host<br />
		 */
		[Bindable]
		protected var currentHost:String = "";
		/**
		 * current port<br />
		 */
		[Bindable]
		protected var currentPort:Number = 21;
		/**
		 * current login<br />
		 */
		[Bindable]
		protected var currentLogin:String;
		/**
		 * current pass<br />
		 */
		[Bindable]
		protected var currentPass:String;
		/**
		 * connected to ftp server or not?<br />
		 */
		[Bindable]
		protected var connected:Boolean = false;
		/**
		 * FTP client class for browsing
		 */
		protected var remoteFileBrowserApplication:RemoteFileBrowserApplication;
		/**
		 * constructor
		 */
		public function Lexapplication():void 
		{
			trace("Lexapplication");
			remoteFileBrowserApplication = new RemoteFileBrowserApplication;
			remoteFileBrowserApplication.initialize();
			initFTPListeners();
			addEventListener("creationComplete", initUIs);
		}
		/**
		 * init UIs
		 */
		private function initUIs(e:Event):void 
		{
			//showLogin();
		}
		private function initFTPListeners():void 
		{
			remoteFileBrowserApplication.addEventListener(RemoteFileBrowserApplication.EVENT_CONNECTION_SUCCESS,connectionSuccessCallback);
			remoteFileBrowserApplication.addEventListener(RemoteFileBrowserApplication.EVENT_CONNECTION_ERROR,connectionSuccessCallback);
				//		EVENT_AUTH_ERROR
			remoteFileBrowserApplication.addEventListener(RemoteFileBrowserApplication.EVENT_AUTH_SUCCESS,connectionSuccessCallback);
			remoteFileBrowserApplication.addEventListener(RemoteFileBrowserApplication.EVENT_AUTH_SUCCESS,connectionSuccessCallback);
				//		EVENT_DIRECTORY_LISTING_ERROR
			remoteFileBrowserApplication.addEventListener(RemoteFileBrowserApplication.EVENT_DIRECTORY_LISTING_SUCCESS,connectionSuccessCallback);
			remoteFileBrowserApplication.addEventListener(RemoteFileBrowserApplication.EVENT_CURRENT_DIRECTORY_CHANGED,connectionSuccessCallback);

			remoteFileBrowserApplication.addEventListener(RemoteFileBrowserApplication.EVENT_FILE_UPLOAD_FINISHED,connectionSuccessCallback);
			remoteFileBrowserApplication.addEventListener(RemoteFileBrowserApplication.EVENT_FILE_UPLOAD_STARTED,connectionSuccessCallback);
			remoteFileBrowserApplication.addEventListener(RemoteFileBrowserApplication.EVENT_BATCH_UPLOAD_FINISHED,connectionSuccessCallback);
			remoteFileBrowserApplication.addEventListener(RemoteFileBrowserApplication.EVENT_BATCH_UPLOAD_STARTED,connectionSuccessCallback);
			remoteFileBrowserApplication.addEventListener(RemoteFileBrowserApplication.EVENT_UPLOAD_ERROR,connectionSuccessCallback);
			remoteFileBrowserApplication.addEventListener(RemoteFileBrowserApplication.EVENT_UPLOAD_PROGRESS,connectionSuccessCallback);

			remoteFileBrowserApplication.addEventListener(RemoteFileBrowserApplication.ERROR_BROWSE_CLIENT_BUSY,connectionSuccessCallback);
			remoteFileBrowserApplication.addEventListener(RemoteFileBrowserApplication.ERROR_FTP_ERROR,connectionSuccessCallback);
			remoteFileBrowserApplication.addEventListener(RemoteFileBrowserApplication.ERROR_FILE_ALLREADY_UPLOADING,connectionSuccessCallback);
		}
		
		
		/////////////////////////////////////////////////////////////////////////////////////
		// processing methods
		/////////////////////////////////////////////////////////////////////////////////////
		
		/**
		 * debug log
		 */
		protected function logMessage(m:String):void 
		{
			Debug.log(m,0x00FFFF);
		}
		// Open the pop-up window.
		protected function showLogin():void 
		{
			// Create a non-modal TitleWindow container.
			var helpWindow:AuthPopup = PopUpManager.createPopUp(this, AuthPopup, false) as AuthPopup;
			PopUpManager.centerPopUp(helpWindow);
			helpWindow.addEventListener("authPopupOk", authPopupOkCallback); 
		}
		/////////////////////////////////////////////////////////////////////////////////////
		// FTP callbacks
		/////////////////////////////////////////////////////////////////////////////////////
		/**
		 * 
		 */
		private function connectionSuccessCallback(e:Event):void 
		{
			trace("Lexapplication connectionSuccessCallback " + e.type);
			switch (e.type)
			{
				case RemoteFileBrowserApplication.EVENT_DIRECTORY_LISTING_SUCCESS:
					logMessage(" - " + remoteFileBrowserApplication.remoteFilesArray.length + " files");
					filesArray.source = remoteFileBrowserApplication.remoteFilesArray;
					dispatchEvent(e);
					break;
				case RemoteFileBrowserApplication.EVENT_CURRENT_DIRECTORY_CHANGED:
					currentPath = remoteFileBrowserApplication.currentRemotePath;
					list();
					break;
				case RemoteFileBrowserApplication.EVENT_CONNECTION_ERROR:
					currentPath = "";
					currentHostAndPort = "";
					connected = false;
					break;
				case RemoteFileBrowserApplication.EVENT_AUTH_SUCCESS:
					trace("AUTH_SUCCESS "+remoteFileBrowserApplication.userLogin);
					currentLogin = remoteFileBrowserApplication.userLogin;
					currentPass = remoteFileBrowserApplication.userPass;
					connected = true;
					cd(currentPath);
					break;
				case RemoteFileBrowserApplication.ERROR_FTP_ERROR:
					currentLogin = null;
					currentPass = null;
					connected = true;
					cd(currentPath);
					break;
				default:
					logMessage(" - unhandled event: "+e.type);
			}
			logMessage(e.toString());
		}
		private function authPopupOkCallback(e:Event):void 
		{
			var helpWindow:AuthPopup = e.currentTarget as org.lexapp.components.AuthPopup;
			helpWindow.removeEventListener("authPopupOk", authPopupOkCallback); 
			connect(helpWindow.connectionLogin, helpWindow.connectionPass);
		}
		/////////////////////////////////////////////////////////////////////////////////////
		// UI callback
		/////////////////////////////////////////////////////////////////////////////////////
		/**
		 * an item has been selected in the files list
		 */
		protected function select(item:FTPFile):void 
		{
			if (item.isDir == true) 
			{
				cd(item.name);
			}
		}
		/**
		 * an item has been selected in the bookmark bar
		 * @param	bookmark	Bookmark object
		 */
		protected function openBookmark(bookmark:BookmarkVO):void 
		{
			trace("Lexapplication openBookmark " +bookmark.label );
			//currentLogin = bookmark.login;
			//currentPass = bookmark.pass;
			//changeHostPortPath(bookmark.host + ":" + bookmark.port.toString());
			
			currentHost = bookmark.host;
			currentPort = bookmark.port;
			currentHostAndPort = currentHost + ":" + currentPort;
			connect(bookmark.login, bookmark.pass);
		}
		/////////////////////////////////////////////////////////////////////////////////////
		// FTP functions
		/////////////////////////////////////////////////////////////////////////////////////
		/**
		 * connect to the FTP server
		 */
		public function connect(connectionLogin:String, connectionPass:String):void 
		{
			if (connected) disconnect();
			
			trace("Lexapplication connect " + connectionLogin + "@" + currentHost + ":" + currentPort);
			
			remoteFileBrowserApplication.connect(connectionLogin, connectionPass, currentHost, currentPort);
		}
		/**
		 * connect to the FTP server
		 */
		public function disconnect():void 
		{
			remoteFileBrowserApplication.closeConnection();
			filesArray = new ArrayList;
		}
		/**
		 * list current folder
		 */
		public function list():void 
		{
			trace("Lexapplication list ");
			remoteFileBrowserApplication.list(currentPath);
		}
		/**
		 * 
		 */
		public function changeHostPortPath(hostPortPath:String):void 
		{
			logMessage("changeHostPortPath " + hostPortPath);
			
			if (hostPortPath=="")
				return;
			
			// remove ftp://
			if (hostPortPath.substr(0, 6) == "ftp://") 
				hostPortPath = hostPortPath.substr(6);
			
			// extract host and port
			var idxSemicol:Number = hostPortPath.indexOf(":");
			var idxFirstSlash:Number = hostPortPath.indexOf("/");
			if (idxFirstSlash == -1) idxFirstSlash = hostPortPath.length;
			if (idxSemicol > -1)
			{
				currentHost = hostPortPath.substr(0,idxSemicol);
				currentPort = parseInt(hostPortPath.substr(idxSemicol+1, idxFirstSlash));
			}
			else
			{
				currentHost = hostPortPath.substr(0,idxFirstSlash);
				currentPort = DEFAULT_PORT;
			}
			currentHostAndPort = hostPortPath.substr(0,idxFirstSlash);
			
			// extract path
			currentPath = hostPortPath.substr(idxFirstSlash);
			
			logMessage(currentHost+" - "+currentPort+" - "+currentHostAndPort+" - "+currentPath);

			// list folder
			cd(currentPath);
		}
		/**
		 * change the current folder<br />
		 * you can pass relative path, begining with "../" or the name of a folder - for now only one level at a time (no "folder1/folder2/")<br />
		 * you can pass absolute path, begining with "/"
		 */
		public function cd(path:String):void 
		{
			logMessage('cd ' + path);
			
			// the resulting absolute path
			var computedPath:String = path;
			
			if (path.substr(0, 1) != "/")
			{
				// convert relative path to absolute path
				if (path == ".")
				{
					// no change
					computedPath = currentPath;
				}
				else
				{
					// get the current path as an array
					var pathArray:Array = currentPath.split("/");
					
					// UP case
					if (path == "..")
					{
						if (pathArray.length > 1)
						{
							pathArray.pop();
						}
					}
					else 
					{
						// a folder name case 
						pathArray.push(path);
					}
					// build the path
					computedPath = pathArray.join("/");
					computedPath += "/";
				}
			}
			
			if (connected == true)
			{
				remoteFileBrowserApplication.cd(computedPath);
			}
			else
			{
				currentPath = computedPath;
				// if needed ask for login/pass and connect
				if (!currentLogin && !currentPass)
				{
					showLogin();
				}
				else
				{
					connect(currentLogin, currentPass);
				}
			}
		}
	}
	
}